哈囉,大家好!
歡迎來到三十天說寫就寫的Coding文章。
有人說「 每個人的一生中至少要有兩次衝動,一次為奮不顧身的愛情,一次為說走就走的旅行。 」
套在Coding的人上,也就是要有幾篇說寫就寫的文章吧!
今天來寫一下Javascript,並使用Javascript來實作一個Stack物件。
首先,我們要先複習一下Javascript的apply跟call方法,因為我們等一下會用到。
在javascript裡,每個function都擁有apply跟call方法,可以用來讓函數方法執行時的this綁定為要使用該方法的物件上,這裡我主要介紹apply。
fun.apply(thisArg, [argsArray])
第一個參數是要使用該function方法(簡稱func)的物件,當第一個參數的值是null或undefined時,非嚴格模式下,func套用的this會是全域物件,否則為null跟undefined。
第二個參數則是將引數們包在一個Array傳給讓function方法使用的參數們。
call方法和apply大同小異,差別只在參數要一個一個輸入。
fun.call(thisArg, arg1, arg2, ...)
使用範例:
在JS裡我們要比較各個數值中的最大值,可以使用Math.max()方法
舉例: Math.max(1, 2, 3, 4) // 該方法返回最大值4
。
使用Math.max方法要將要比較的數值一個一個輸入進去,如果現在我們要找出一個Array內各個數值的最大值,
這時候沒有apply或call方法,要對Array做很多處理才能算出數值,多不方便啊。
是時候輪到apply方法出場了。
const max = (...args) => Math.max.apply(null, args);
const arr = [1,2,3,4,5];
max(...arr); // 該方法返回最大值5
從上面的範例可以看到,使用apply方法,一行就可以將我們要使用的max方法使用apply成一個適合array使用的function,多麼簡單就完成了這個需求阿!
現在我們會使用apply方法了,該進到我們今天的主題: 實作一個Stack。
Stack(堆疊)是一個依照後進先出(LIFO)原則設計的有序集合。
我們可以想像我們在一個塞好幾個羽球的長筒,最先放進去的一定是最後拿出來,最後放進去的反而可以先拿出來。
這個比喻完全適用在Stack的行為上。
好,現在我們要來設計一個Stack的類別。
Stack類別下面要擁有如下方法:
讓我們開始寫一個Stack的基本骨架
class Stack {
length = 0;
constructor() {}
add() {}
pop() {}
last() {}
size() {}
clear() {}
isEmpty() {}
}
Ok,現在我們的class大致有了個樣子,接下來,我們要實作add方法!
add(...elems) {
Array.prototype.push.apply(this, elems);
}
加入了Add方法後,我們來建立這個Stack物件,並且測試一下。
const stack = new Stack();
console.log('Stack Length:', stack.length);
stack.add('el1', 'el2');
console.log('Stack Length:', stack.length);
神奇的地方來囉!
// 輸出結果:
// Stack Length: 0
// Stack Length: 2
明明是使用Array的方法,但是Stack類別的length屬性居然也跟著改變了!
原來,Array方法本身會增加Array物件屬性的長度(length),現在我們用apply將Array套用在Stack的this上,因為this指向改變,所以push改為影響到Stack的length屬性。
只要好好把握這個原理,用Array內建的方法就可以完成許多建構Stack方法要處理的事情囉!
Ok,最後最後,我們舉一反三,完成一個簡潔的Stack,並且進行簡單的測試。
精髓盡在程式碼中,仔細感受一下吧!
如果有地方看不明白或不了解,建議多趁這個機會查詢,並進一步了解JS的語法跟Array的方法。
class Stack {
length = 0;
constructor() {}
add(...elems) {
Array.prototype.push.apply(this, elems);
}
pop() {
return Array.prototype.pop.apply(this);
}
last() {
return this[this.length-1];
}
size() {
return this.length;
}
clear() {
Array.prototype.splice.apply(this, [0, this.length]);
}
isEmpty() {
return this.length === 0;
}
}
最後這是測試用代碼,建議讀者親自操作,透過主控台檢視下Stack物件的狀態,才會有新的體會!
console.log('Stack', stack);
console.log('Stack Length:', stack.length);
stack.add('el1', 'el2');
console.log('Stack Length:', stack.length);
const popElem = stack.pop();
console.log('Stack Length:', stack.length);
console.log('PopElem:', popElem);
console.log('last: ', stack.last());
stack.add('el3','el4', 'el5');
console.log('stack: ', stack);
stack.clear();
console.log('stack: ', stack);
console.log('IsEmpty: ', stack.isEmpty());
好的,以上這就是今天的全部內容囉,希望各位能夠照著操作,並且有滿滿的收穫。
我們明天見,掰掰!